﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using PengSW.UdpHelper;
using static PengSW.RuntimeLog.RL;

namespace UdpToolkit
{
    class MainModel : INotifyPropertyChanged
    {
        public MainModel()
        {
            _Listener.Received += OnListener_Received;
            _Listener.Error += OnListener_Error;
        }

        private void OnListener_Error(object sender, string aErrorMessage)
        {
            L($"Receiver Error: {aErrorMessage}");
        }

        private void OnListener_Received(object sender, string aMessage)
        {
            L($"Receive: {aMessage}");
        }

        public string SendToHost { get => _SendToHost; set { if (_SendToHost == value) return; _SendToHost = value; OnPropertyChanged(nameof(SendToHost)); } }
        private string _SendToHost = "127.0.0.1";

        public int SendToPort { get => _SendToPort; set { if (_SendToPort == value) return; _SendToPort = value; OnPropertyChanged(nameof(SendToPort)); } }
        private int _SendToPort = 15551;

        public string SendContent { get => _SendContent; set { if (_SendContent == value) return; _SendContent = value; OnPropertyChanged(nameof(SendContent)); } }
        private string _SendContent;

        public Encoding SendEncoding { get => _SendEncoding; set { if (_SendEncoding == value) return; _SendEncoding = value; OnPropertyChanged(nameof(SendEncoding)); } }
        private Encoding _SendEncoding = Encoding.UTF8;

        public ObservableCollection<string> SendHistory { get; } = new ObservableCollection<string>();

        public void AddHistory(string aHistory)
        {
            if (!SendHistory.Contains(aHistory))
                SendHistory.Add(aHistory);
        }

        public void Send()
        {
            L($"Send: {SendContent}");
            UdpListener.Send(SendToHost, SendToPort, SendContent, SendEncoding);
            AddHistory(SendContent);
        }

        internal void Broadcast()
        {
            throw new NotImplementedException();
        }

        public bool CanSend => !string.IsNullOrWhiteSpace(SendToHost) && SendToPort > 0 && !string.IsNullOrEmpty(SendContent);

        private readonly UdpListener _Listener = new UdpListener();
        public int ListenPort { get => _Listener.ListenPort; set { _Listener.ListenPort = value; OnPropertyChanged(nameof(ListenPort)); } }
        public Encoding ReceiveEncoding { get => _Listener.ReceiveEncoding; set { _Listener.ReceiveEncoding = value; OnPropertyChanged(); } }
        public void GetFreePort() => ListenPort = UdpListener.GetFreePort();
        public void StartListen() => _Listener.StartListen();
        public void StopListen() => _Listener.StopListen();
        public bool CanStartListen => _Listener.CanStartListen;
        public bool CanStopListen => _Listener.CanStopListen;
        public bool CanGetFreePort => !CanStopListen;

        public Encoding[] Encodings => _Encodings;

        public bool CanBroadcast { get; internal set; }

        private static readonly Encoding[] _Encodings = new Encoding[] { Encoding.Default, Encoding.ASCII, Encoding.UTF8, Encoding.UTF32, Encoding.UTF7, Encoding.BigEndianUnicode, Encoding.Unicode };

        private void OnPropertyChanged([CallerMemberName] string aPropertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(aPropertyName));
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
